# 语音识别模块 - 增强版
import speech_recognition as sr
import pyaudio
import threading
import time
import re
import logging
import sys
from collections import deque
from config import LANGUAGE, SAMPLE_RATE, CHUNK_SIZE, WAKE_WORD, LOG_LEVEL

# 配置日志，确保使用UTF-8编码
logging.basicConfig(
    level=getattr(logging, LOG_LEVEL),
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler("voice_recognition.log", encoding='utf-8'),
        logging.StreamHandler(sys.stdout)
    ]
)
logger = logging.getLogger(__name__)


class VoiceRecognizer:
    def __init__(self, timeout=15, min_confidence=0.7, audio_buffer_size=5):
        self.recognizer = sr.Recognizer()
        self.microphone = sr.Microphone()
        self.running = False
        self.callback = None
        self.wake_word_detected = False
        # 支持多唤醒词
        self.wake_words = [WAKE_WORD] if isinstance(WAKE_WORD, str) else WAKE_WORD
        self.is_listening_for_command = False  # 标记是否正在等待用户命令
        self.last_realtime_text = ""  # 存储最后一次实时识别的文本
        self.last_sound_time = time.time()  # 记录最后一次检测到声音的时间
        self.silent_threshold = 2.0  # 静默阈值(秒)
        self.consecutive_recognition_attempts = 0  # 连续识别尝试次数
        self.max_consecutive_attempts = 3  # 最大连续尝试次数
        self.timeout = timeout  # 识别超时时间
        self.min_confidence = min_confidence  # 最小置信度
        # 使用deque作为音频缓冲区，优化性能
        self.audio_buffer = deque(maxlen=audio_buffer_size)
        self.last_wake_time = 0  # 记录最后一次唤醒时间，避免重复唤醒
        self.wake_cooldown = 2  # 唤醒冷却时间(秒)
        logger.info("语音识别器初始化完成")
        # 尝试初始化备用识别服务
        self.has_vosk = False
        try:
            import vosk
            self.has_vosk = True
            logger.info("已检测到Vosk，将作为备用语音识别引擎")
        except ImportError:
            logger.warning("未检测到Vosk，无法使用离线识别功能")
        
    def set_callback(self, callback):
        """设置识别到文本后的回调函数"""
        self.callback = callback
    
    def set_text_to_speech(self, text_to_speech_func):
        """设置文本到语音转换函数，避免循环导入"""
        self._text_to_speech_func = text_to_speech_func
    
    def recognize_from_microphone(self):
        """从麦克风识别语音 - 增强版，支持多识别引擎备选"""
        with self.microphone as source:
            logger.info("正在监听...")
            # 调整环境噪音水平，使用更长的校准时间
            self.recognizer.adjust_for_ambient_noise(source, duration=1.5)
            try:
                # 开始录音，支持更灵活的超时设置
                audio = self.recognizer.listen(source, timeout=self.timeout, phrase_time_limit=self.timeout)
                
                # 尝试使用Google Speech Recognition API识别
                try:
                    text = self.recognizer.recognize_google(audio, language=LANGUAGE)
                    logger.info(f"识别结果: {text}")
                    return text
                except sr.RequestError as e:
                    logger.warning(f"Google语音识别服务不可用: {e}，尝试备用方案")
                    # 尝试使用离线识别或其他服务
                    if self.has_vosk:
                        return self._recognize_with_vosk(audio)
                    else:
                        raise
                except Exception as e:
                    logger.error(f"识别错误: {str(e)}")
                    raise
            except sr.UnknownValueError:
                logger.info("无法识别语音")
                return ""
            except Exception as e:
                logger.error(f"麦克风识别错误: {str(e)}")
                return ""
                
    def _recognize_with_vosk(self, audio):
        """使用Vosk进行离线语音识别"""
        try:
            import vosk
            import json
            # 简单的中文模型路径示例，实际使用需要下载对应的模型文件
            model_path = "model"
            
            # 检查模型是否存在
            import os
            if not os.path.exists(model_path):
                logger.warning(f"Vosk模型文件不存在: {model_path}，跳过离线识别")
                return ""
                
            model = vosk.Model(model_path)
            recognizer = vosk.KaldiRecognizer(model, SAMPLE_RATE)
            
            # 转换音频数据
            audio_data = audio.get_raw_data()
            recognizer.AcceptWaveform(audio_data)
            result = json.loads(recognizer.FinalResult())
            text = result.get("text", "").strip()
            
            logger.info(f"Vosk离线识别结果: {text}")
            return text
        except Exception as e:
            logger.error(f"Vosk离线识别失败: {str(e)}")
            return ""
    
    def wake_word_detection(self, audio):
        """检测唤醒词 - 增强版，支持多唤醒词、置信度检查和防重复唤醒"""
        # 检查冷却时间，避免重复唤醒
        current_time = time.time()
        if current_time - self.last_wake_time < self.wake_cooldown:
            return
            
        try:
            # 构建识别参数，尝试使用置信度
            kwargs = {'language': LANGUAGE}
            # Google API不直接返回置信度，但其他API可能支持
            
            # 尝试识别文本
            text = self.recognizer.recognize_google(audio, **kwargs)
            
            # 更新最后一次声音时间
            self.last_sound_time = current_time
            
            # 实时显示所有识别到的文本
            if text and text != self.last_realtime_text:
                logger.info(f"🔊 识别到声音: {text}")
                print(f"🔊 识别到声音: {text}")
                self.last_realtime_text = text
            
            # 检查是否包含任一唤醒词
            detected_wake_word = None
            for wake_word in self.wake_words:
                if wake_word in text:
                    detected_wake_word = wake_word
                    break
            
            if detected_wake_word and not self.wake_word_detected:
                logger.info(f"✅ 检测到唤醒词: {detected_wake_word}")
                print(f"✅ 检测到唤醒词: {detected_wake_word}")
                
                # 更新唤醒时间
                self.last_wake_time = current_time
                
                # 播放确认提示音，告知用户已听到唤醒词
                if hasattr(self, '_text_to_speech_func') and self._text_to_speech_func:
                    self._text_to_speech_func("我在，请说")
                else:
                    print("🔊 我在，请说")
                
                self.wake_word_detected = True
                self.is_listening_for_command = True
                
                # 去除唤醒词，只保留命令部分
                command = text.replace(detected_wake_word, "").strip()
                if command and self.callback:
                    logger.info(f"📝 处理命令: {command}")
                    print(f"📝 处理命令: {command}")
                    self.callback(command)
                    # 处理完命令后重置状态
                    self.wake_word_detected = False
                    self.is_listening_for_command = False
                    self.consecutive_recognition_attempts = 0
        except sr.UnknownValueError:
            # 未知语音，不做处理
            self.consecutive_recognition_attempts += 1
            if self.consecutive_recognition_attempts >= self.max_consecutive_attempts:
                self.consecutive_recognition_attempts = 0
        except sr.RequestError as e:
            logger.error(f"语音识别服务错误: {e}")
            # 尝试使用备用识别器
            if self.has_vosk:
                self._try_vosk_for_wake_word(audio)
        except Exception as e:
            logger.error(f"唤醒词检测错误: {str(e)}")
    
    def _try_vosk_for_wake_word(self, audio):
        """尝试使用Vosk进行离线唤醒词检测"""
        try:
            text = self._recognize_with_vosk(audio)
            if not text:
                return
                
            current_time = time.time()
            self.last_sound_time = current_time
            
            # 检查是否包含任一唤醒词
            detected_wake_word = None
            for wake_word in self.wake_words:
                if wake_word in text:
                    detected_wake_word = wake_word
                    break
            
            if detected_wake_word and not self.wake_word_detected:
                logger.info(f"✅ Vosk检测到唤醒词: {detected_wake_word}")
                print(f"✅ Vosk检测到唤醒词: {detected_wake_word}")
                
                self.last_wake_time = current_time
                
                if hasattr(self, '_text_to_speech_func') and self._text_to_speech_func:
                    self._text_to_speech_func("我在，请说")
                else:
                    print("🔊 我在，请说")
                
                self.wake_word_detected = True
                self.is_listening_for_command = True
        except Exception as e:
            logger.error(f"Vosk唤醒词检测失败: {str(e)}")
    
    def start_listening(self):
        """开始持续监听"""
        self.running = True
        threading.Thread(target=self._listening_thread, daemon=True).start()
    
    def stop_listening(self):
        """停止监听"""
        self.running = False
    
    def _listening_thread(self):
        """监听线程 - 增强版，优化音频分析、噪音检测和系统资源管理"""
        try:
            p = pyaudio.PyAudio()
            # 检查并选择最佳音频设备
            device_index = self._get_best_input_device(p)
            
            stream = p.open(
                format=pyaudio.paInt16,
                channels=1,
                rate=SAMPLE_RATE,
                input=True,
                frames_per_buffer=CHUNK_SIZE,
                input_device_index=device_index
            )
            
            logger.info("🎙️  语音助手已启动，正在监听声音和唤醒词...")
            print("🎙️  语音助手已启动，正在监听声音和唤醒词...")
            wake_words_text = "或".join(self.wake_words)
            print(f"💡 提示: 说'{wake_words_text}'唤醒我，然后说出您的命令")
            
            # 用于记录最后一次状态提示的时间
            last_status_time = time.time()
            last_sound_activity_time = time.time()
            
            # 使用deque作为音频缓冲区，优化性能和内存使用
            audio_buffer = deque(maxlen=5)  # 约1秒的数据
            
            # 初始化音频分析器
            audio_analyzer = AudioAnalyzer()
            
            # 校准阶段：前3秒用于环境噪音校准
            calibration_frames = []
            calibration_time = 3  # 校准时间(秒)
            calibration_start_time = time.time()
            print("🔊 正在校准麦克风，请保持环境安静...")
            
            while self.running:
                try:
                    data = stream.read(CHUNK_SIZE)
                    
                    # 计算音频能量，用于检测是否有声音
                    energy = self._calculate_audio_energy(data)
                    
                    # 校准阶段处理
                    current_time = time.time()
                    if current_time - calibration_start_time < calibration_time:
                        calibration_frames.append(data)
                        # 每隔0.5秒显示校准进度
                        if current_time - calibration_start_time > len(calibration_frames) * 0.5:
                            progress = int((current_time - calibration_start_time) / calibration_time * 100)
                            print(f"🔊 校准进度: {progress}%")
                        continue
                    elif calibration_frames:
                        # 校准完成，处理校准数据
                        calibration_audio = b''.join(calibration_frames)
                        audio_analyzer.calibrate_noise(calibration_audio)
                        calibration_frames = []
                        print("✅ 麦克风校准完成")
                    
                    # 更新音频缓冲区
                    audio_buffer.append(data)
                    
                    # 使用改进的音频分析器检测是否有语音活动
                    is_speech_activity = audio_analyzer.is_speech(data) or energy > 1500
                    
                    # 检测到有声音时更新时间戳
                    if is_speech_activity:
                        last_sound_activity_time = current_time
                        
                        # 构建连续的音频数据用于识别
                        if len(audio_buffer) >= 3:  # 至少有0.6秒的数据
                            continuous_audio_data = b''.join(audio_buffer)
                            continuous_audio = sr.AudioData(continuous_audio_data, SAMPLE_RATE, 2)
                        else:
                            continuous_audio = sr.AudioData(data, SAMPLE_RATE, 2)
                    else:
                        # 静默状态，适当清理缓冲区
                        if len(audio_buffer) > 2:
                            # 保留一些历史数据以捕捉开始的语音
                            audio_buffer = deque(list(audio_buffer)[-2:], maxlen=5)
                        
                        # 检查是否需要重置状态提示时间
                        if current_time - last_sound_activity_time > 10:
                            last_status_time = current_time - 2  # 再过1秒显示状态
                    
                    # 如果正在等待命令，显示提示
                    if self.is_listening_for_command:
                        # 每隔4秒显示一次状态提示，减少干扰
                        if current_time - last_status_time > 4:
                            print("🔍 正在等待您的命令...")
                            last_status_time = current_time
                    
                    # 根据状态进行不同处理
                    if not self.wake_word_detected:
                        # 只有在检测到语音活动时才进行唤醒词识别，减少API调用
                        if is_speech_activity:
                            self.wake_word_detection(continuous_audio if 'continuous_audio' in locals() else sr.AudioData(data, SAMPLE_RATE, 2))
                    elif self.is_listening_for_command:
                        # 唤醒后继续监听用户命令
                        try:
                            if is_speech_activity:
                                # 尝试多种识别方法
                                text = None
                                try:
                                    # 优先尝试Google API
                                    text = self.recognizer.recognize_google(continuous_audio if 'continuous_audio' in locals() else sr.AudioData(data, SAMPLE_RATE, 2), language=LANGUAGE)
                                except (sr.UnknownValueError, sr.RequestError):
                                    # 如果失败，尝试Vosk
                                    if self.has_vosk and 'continuous_audio' in locals():
                                        text = self._recognize_with_vosk(continuous_audio)
                                
                                if text and self.callback:
                                    logger.info(f"📝 识别到命令: {text}")
                                    print(f"📝 识别到命令: {text}")
                                    self.callback(text)
                                    # 处理完命令后重置状态
                                    self.wake_word_detected = False
                                    self.is_listening_for_command = False
                                    print("🎙️  等待下一次唤醒...")
                                    self.consecutive_recognition_attempts = 0
                        except Exception as e:
                            logger.error(f"命令识别错误: {str(e)}")
                    
                    # 检查静默时间，重置状态
                    if self.wake_word_detected and self.is_listening_for_command and current_time - last_sound_activity_time > 15:  # 延长超时时间
                        logger.info("⏱️  等待超时，返回监听模式")
                        print("⏱️  等待超时，返回监听模式")
                        self.wake_word_detected = False
                        self.is_listening_for_command = False
                    
                    # 优化CPU使用，使用动态睡眠
                    time.sleep(0.05)  # 减少到50ms，提高响应速度
                except IOError as e:
                    # 处理音频输入溢出错误
                    logger.error(f"音频输入错误: {e}")
                    if stream:
                        stream.stop_stream()
                        stream.close()
                    stream = p.open(
                        format=pyaudio.paInt16,
                        channels=1,
                        rate=SAMPLE_RATE,
                        input=True,
                        frames_per_buffer=CHUNK_SIZE,
                        input_device_index=device_index
                    )
                    time.sleep(0.1)
                except Exception as e:
                    logger.error(f"监听线程错误: {str(e)}")
                    time.sleep(0.1)
            
            stream.stop_stream()
            stream.close()
            p.terminate()
            logger.info("🔇 语音助手已停止监听")
            print("🔇 语音助手已停止监听")
        except Exception as e:
            logger.error(f"启动监听线程失败: {str(e)}")
            print(f"❌ 启动语音监听失败: {str(e)}")
    
    def _get_best_input_device(self, pyaudio_instance):
        """获取最佳输入设备索引"""
        try:
            device_count = pyaudio_instance.get_device_count()
            default_device = pyaudio_instance.get_default_input_device_info()
            logger.info(f"默认输入设备: {default_device['name']}")
            
            # 尝试找到麦克风设备
            for i in range(device_count):
                device_info = pyaudio_instance.get_device_info_by_index(i)
                device_name = device_info['name'].lower()
                if device_info['maxInputChannels'] > 0 and (
                    'mic' in device_name or '麦克风' in device_name or 
                    'microphone' in device_name or 'mic' in device_name):
                    logger.info(f"选择麦克风设备: {device_info['name']}")
                    return i
            
            # 返回默认输入设备
            return default_device['index']
        except Exception as e:
            logger.error(f"获取音频设备失败: {e}")
            return None
    
    def _calculate_audio_energy(self, audio_data):
        """计算音频能量，用于检测是否有声音 - 增强版，更稳定的能量计算"""
        try:
            import numpy as np
            # 将音频数据转换为numpy数组
            audio_array = np.frombuffer(audio_data, dtype=np.int16)
            
            # 使用更鲁棒的能量计算方法
            # 1. 计算绝对值的平均值作为能量指标
            abs_mean = np.mean(np.abs(audio_array))
            
            # 2. 计算RMS能量
            rms = np.sqrt(np.mean(np.square(audio_array)))
            
            # 3. 结合两种方法，提高检测稳定性
            energy = max(abs_mean, rms / 2)
            
            return energy
        except ImportError:
            # 如果没有numpy，使用备用计算方法
            try:
                # 简单的能量计算，适用于没有numpy的情况
                total_energy = 0
                for i in range(0, len(audio_data), 2):
                    if i + 1 < len(audio_data):
                        sample = (audio_data[i] << 8) | audio_data[i + 1]
                        total_energy += sample * sample
                return int(total_energy / len(audio_data)) if audio_data else 0
            except:
                return 0
        except Exception as e:
            logger.error(f"音频能量计算错误: {e}")
            return 0

class TextToSpeechEngine:
    """文本到语音转换引擎 - 增强版，支持多引擎、语音队列和状态管理"""
    
    def __init__(self):
        self.available_engines = []
        self.active_engine = None
        self.voice_queue = []  # 语音队列，避免重叠播放
        self.is_speaking = False
        self.lock = threading.Lock()
        self.rate = None
        self.volume = None
        
        # 尝试初始化不同的TTS引擎
        self._initialize_engines()
    
    def _initialize_engines(self):
        """初始化可用的TTS引擎"""
        try:
            from config import VOICE_RATE, VOICE_VOLUME
            self.rate = VOICE_RATE
            self.volume = VOICE_VOLUME
        except ImportError:
            # 默认配置
            self.rate = 150
            self.volume = 1.0
        
        # 尝试初始化pyttsx3引擎
        try:
            import pyttsx3
            engine = pyttsx3.init()
            # 预先设置参数
            engine.setProperty('rate', self.rate)
            engine.setProperty('volume', self.volume)
            
            # 尝试选择最佳语音
            voices = engine.getProperty('voices')
            best_voice = None
            
            # 中文语音优先
            for voice in voices:
                voice_id = voice.id.lower()
                voice_name = voice.name.lower() if hasattr(voice, 'name') else ''
                if any(keyword in voice_id or keyword in voice_name 
                       for keyword in ['chinese', 'china', 'zh', 'mandarin', '中文']):
                    best_voice = voice.id
                    break
            
            if best_voice:
                engine.setProperty('voice', best_voice)
                logger.info(f"已设置中文语音: {best_voice}")
            else:
                logger.warning("未找到理想的中文语音，使用系统默认语音")
            
            self.available_engines.append(('pyttsx3', engine))
            self.active_engine = engine
            logger.info("pyttsx3 TTS引擎初始化成功")
        except Exception as e:
            logger.error(f"初始化pyttsx3引擎失败: {e}")
    
    def speak(self, text):
        """播放文本，支持队列管理"""
        if not text or not text.strip():
            return
        
        with self.lock:
            self.voice_queue.append(text)
            # 如果当前没有在说话，启动播放线程
            if not self.is_speaking:
                threading.Thread(target=self._speak_queue, daemon=True).start()
    
    def _speak_queue(self):
        """处理语音队列"""
        with self.lock:
            self.is_speaking = True
        
        while self.voice_queue:
            with self.lock:
                if not self.voice_queue:
                    break
                text = self.voice_queue.pop(0)
            
            self._speak_text(text)
            # 小延迟，确保语音不重叠
            time.sleep(0.1)
        
        with self.lock:
            self.is_speaking = False
    
    def _speak_text(self, text):
        """使用活动引擎播放文本"""
        logger.info(f"🔊 语音输出: {text}")
        print(f"🔊 语音输出: {text}")
        
        # 首先尝试使用活动引擎
        if self.active_engine:
            try:
                self.active_engine.say(text)
                self.active_engine.runAndWait()
                return
            except Exception as e:
                logger.error(f"使用活动TTS引擎失败: {e}")
        
        # 如果失败，尝试所有可用引擎
        for engine_name, engine in self.available_engines:
            if engine == self.active_engine:
                continue  # 已经尝试过
                
            try:
                logger.info(f"尝试使用备用引擎: {engine_name}")
                engine.say(text)
                engine.runAndWait()
                return
            except Exception as e:
                logger.error(f"使用{engine_name}引擎失败: {e}")
        
        # 如果所有引擎都失败，尝试创建新的临时引擎
        try:
            import pyttsx3
            temp_engine = pyttsx3.init()
            temp_engine.setProperty('rate', self.rate)
            temp_engine.setProperty('volume', self.volume)
            temp_engine.say(text)
            temp_engine.runAndWait()
            logger.info("成功使用临时TTS引擎")
        except Exception as e:
            logger.error(f"所有TTS引擎都失败了: {e}")
            # 作为最后的后备，打印到控制台
            print(f"💬 [无法播放语音]: {text}")
    
    def stop(self):
        """停止所有语音播放"""
        with self.lock:
            self.voice_queue.clear()
        
        # 尝试停止活动引擎
        if self.active_engine:
            try:
                self.active_engine.stop()
            except:
                pass
        
        logger.info("语音播放已停止")
    
    def set_parameters(self, rate=None, volume=None):
        """设置语音参数"""
        with self.lock:
            if rate is not None:
                self.rate = rate
                for _, engine in self.available_engines:
                    try:
                        engine.setProperty('rate', rate)
                    except:
                        pass
            
            if volume is not None:
                self.volume = volume
                for _, engine in self.available_engines:
                    try:
                        engine.setProperty('volume', volume)
                    except:
                        pass

# 向后兼容的简单接口
def text_to_speech(text):
    """将文本转换为语音输出 - 向后兼容接口"""
    # 懒加载TTS引擎
    global _tts_engine
    if '_tts_engine' not in globals():
        _tts_engine = TextToSpeechEngine()
    
    _tts_engine.speak(text)

class AudioAnalyzer:
    """音频分析工具 - 增强版，用于高级环境噪音检测和声音活动分析"""
    
    def __init__(self):
        self.noise_level = 0
        self.calibrated = False
        self.energy_history = deque(maxlen=20)  # 保存历史能量值
        self.adaptive_threshold = 1000  # 自适应阈值
        self.speech_probability = 0  # 语音概率
        self.noise_floor = 0  # 噪音底限
        self.noise_ceiling = 0  # 噪音上限
        
    def calibrate_noise(self, audio_data):
        """校准环境噪音水平 - 增强版，使用统计方法更准确地估计噪音"""
        try:
            # 分段计算能量，避免异常值影响
            segment_size = 1024
            energies = []
            
            # 计算多个片段的能量
            for i in range(0, len(audio_data), segment_size):
                segment = audio_data[i:i+segment_size]
                if len(segment) < 2:
                    continue
                energy = self._calculate_energy(segment)
                if energy > 0:
                    energies.append(energy)
            
            if not energies:
                logger.warning("无法获取有效能量值，使用默认噪音水平")
                self.noise_level = 500
                self.calibrated = True
                return self.noise_level
            
            # 使用统计方法计算噪音水平，取中位数和四分位数
            import numpy as np
            energies.sort()
            
            # 中位数作为主要噪音水平
            median_energy = np.median(energies)
            
            # 计算噪音底限和上限
            self.noise_floor = np.percentile(energies, 25)  # 第一四分位数
            self.noise_ceiling = np.percentile(energies, 75)  # 第三四分位数
            
            # 设置噪音阈值，增加一些余量
            self.noise_level = median_energy * 1.8
            self.adaptive_threshold = self.noise_level * 1.5
            
            self.calibrated = True
            logger.info(f"噪音校准完成 - 噪音水平: {self.noise_level}, 底限: {self.noise_floor}, 上限: {self.noise_ceiling}")
            
            return self.noise_level
        except Exception as e:
            logger.error(f"噪音校准错误: {e}")
            # 使用默认值
            self.noise_level = 500
            self.calibrated = True
            return self.noise_level
    
    def is_speech(self, audio_data):
        """检测是否有语音活动 - 增强版，结合能量、频谱和时间特征"""
        if not self.calibrated:
            return False
        
        try:
            # 计算当前能量
            current_energy = self._calculate_energy(audio_data)
            
            # 更新能量历史
            self.energy_history.append(current_energy)
            
            # 基本能量检测
            if current_energy < self.noise_level * 1.2:
                # 低于基本阈值，可能是噪音
                self.speech_probability = max(0, self.speech_probability - 0.1)
                return False
            
            # 计算能量变化率
            if len(self.energy_history) > 5:
                # 最近的能量平均值
                recent_avg = np.mean(list(self.energy_history)[-5:])
                # 稍早的能量平均值
                earlier_avg = np.mean(list(self.energy_history)[:-5]) if len(self.energy_history) > 10 else recent_avg
                
                # 能量变化率
                if earlier_avg > 0:
                    energy_change_rate = (recent_avg - earlier_avg) / earlier_avg
                else:
                    energy_change_rate = 0
            else:
                energy_change_rate = 0
            
            # 综合判断
            # 1. 能量阈值判断
            energy_score = min(1.0, current_energy / self.noise_level / 5.0)
            
            # 2. 能量变化率判断
            change_score = max(0, min(1.0, energy_change_rate * 2))
            
            # 3. 与噪音上限比较
            ceiling_score = min(1.0, (current_energy - self.noise_ceiling) / self.noise_ceiling)
            
            # 综合评分
            self.speech_probability = 0.5 * energy_score + 0.3 * change_score + 0.2 * ceiling_score
            
            # 更新自适应阈值
            if self.speech_probability < 0.2:
                # 如果可能是噪音，适当提高噪音底限
                self.noise_floor = max(self.noise_floor, current_energy * 0.8)
                self.adaptive_threshold = min(self.adaptive_threshold * 1.05, self.noise_level * 5)
            
            # 判断是否为语音
            is_speech = self.speech_probability > 0.6 or current_energy > self.adaptive_threshold
            
            return is_speech
        except Exception as e:
            logger.error(f"语音检测错误: {e}")
            # 回退到简单的能量检测
            return self._calculate_energy(audio_data) > self.noise_level * 1.5
    
    def _calculate_energy(self, audio_data):
        """计算音频能量 - 增强版，支持多种能量计算方法"""
        try:
            # 优先使用numpy进行高效计算
            try:
                import numpy as np
                # 将音频数据转换为numpy数组
                audio_array = np.frombuffer(audio_data, dtype=np.int16)
                
                # 计算RMS能量
                rms = np.sqrt(np.mean(np.square(audio_array)))
                
                # 计算峰值能量
                peak = np.max(np.abs(audio_array))
                
                # 计算过零率 (粗略估计)
                sign_changes = np.sum(np.abs(np.diff(np.signbit(audio_array))))
                zero_crossing_rate = sign_changes / len(audio_array)
                
                # 综合能量指标，结合RMS和峰值
                combined_energy = rms + (peak * 0.1)
                
                return combined_energy
            except ImportError:
                # 备用计算方法，适用于没有numpy的情况
                if not audio_data or len(audio_data) < 2:
                    return 0
                    
                total_energy = 0
                peak = 0
                
                # 计算每个样本的能量和峰值
                for i in range(0, len(audio_data), 2):
                    if i + 1 < len(audio_data):
                        # 小端序转换为16位整数
                        if isinstance(audio_data[i], int):
                            sample = (audio_data[i] << 8) | audio_data[i + 1]
                        else:
                            sample = (audio_data[i] << 8) | audio_data[i + 1]
                        
                        # 处理负数
                        if sample >= 0x8000:
                            sample -= 0x10000
                        
                        total_energy += sample * sample
                        peak = max(peak, abs(sample))
                
                # 计算均方根能量
                if len(audio_data) > 0:
                    rms = (total_energy / (len(audio_data) / 2)) ** 0.5
                    return rms + (peak * 0.1)
                else:
                    return 0
        except Exception as e:
            logger.error(f"能量计算错误: {e}")
            return 0
    
    def get_noise_profile(self):
        """获取当前噪音配置文件"""
        return {
            'calibrated': self.calibrated,
            'noise_level': self.noise_level,
            'noise_floor': self.noise_floor,
            'noise_ceiling': self.noise_ceiling,
            'adaptive_threshold': self.adaptive_threshold
        }
    
    def reset(self):
        """重置音频分析器状态"""
        self.noise_level = 0
        self.calibrated = False
        self.energy_history.clear()
        self.adaptive_threshold = 1000
        self.speech_probability = 0
        self.noise_floor = 0
        self.noise_ceiling = 0
        logger.info("音频分析器已重置")